import java.util.HashMap;
import java.util.Map;

import akka.actor.ActorRef;
import akka.actor.UntypedActor;

/**
 * Security station which handles passengers based on results from scanners
 * @author mja2637
 */
public class SecurityStation extends UntypedActor {
	/** Stock indentation for messages from this actor */
	private final String INDENTATION = "      ";
	/** The line number this security station manages */
	private final int lineIndex;
	/** Central jail where passengers are sent post-gropedown */
	private final ActorRef jail;
	/** Maps passengers to the results of their first scan */
	private final Map<Passenger, Boolean> scans;	
	/** How many scanners feed results to this station? */
	private final int numScanners = 2; // because magic #'s are bad
	/** Tracks poison pills received */
	private int pillCount = 0;

	/**
	 * Constructs security station, setting final fields
	 * @param index used to identify this station
	 * @param jail
	 */
	public SecurityStation(int index, ActorRef jail) {
		this.lineIndex = index;
		this.jail = jail;
		this.scans = new HashMap<Passenger, Boolean>();
	}

	@Override
	public void onReceive(Object message) throws Exception {
		if (message instanceof Report) {
			Report rpt = (Report)message;
			String newRptState = (rpt.getScanPassBoolean() ? "Pass" : "Fail");			
			System.out.format("%sSecurity %d: %s report received (%s)\n", 
					INDENTATION, lineIndex, rpt.getPassenger().getName(), newRptState);
			if (scans.containsKey(rpt.getPassenger())) { // This is the second report
				String oldRptState = (scans.get(rpt.getPassenger()) ? "Pass" : "Fail");
				if (!scans.get(rpt.getPassenger()) || !rpt.getScanPassBoolean()) {
					jail.tell(rpt.getPassenger());
					System.out.format("%sSecurity %d: %s (%s/%s) sent to jail\n", 
							INDENTATION, lineIndex, rpt.getPassenger().getName(), oldRptState, newRptState);
				} else System.out.format("%sSecurity %d: %s (%s/%s) released to airport\n", 
						INDENTATION, lineIndex, rpt.getPassenger().getName(), oldRptState, newRptState);
				scans.remove(rpt.getPassenger());
			} else { // This is the first report
				scans.put(rpt.getPassenger(), rpt.getScanPassBoolean());
			}
		} else if (message instanceof Pill) {
			System.out.format("%sSecurity %d: Close received (%d of %d scanners)\n", 
					INDENTATION, lineIndex, pillCount+1, numScanners);
			if (++pillCount >= numScanners) {	// Exit when both pills received			
				jail.tell(new Pill());
				System.out.format("%sSecurity %d: Close sent to jail\n", INDENTATION, lineIndex);
				System.out.format("%sSecurity %d: Closed\n", INDENTATION, lineIndex);
				getContext().stop();
			}
		}
	}
}

